<?php

namespace app\common\model\knowbase;

use fast\Pinyin;
use fast\Tree;
use think\Cache;
use think\Cookie;
use think\Model;
use think\Session;
use traits\model\SoftDelete;

class ProjectPage extends Model
{

    use SoftDelete;



   
    protected $name = 'knowbase_project_page';

   
    protected $autoWriteTimestamp = 'integer';

   
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = 'deletetime';

   
    protected $append = [
        'type_text',
        'access_type_text'
    ];


    protected static function init()
    {
        self::afterInsert(function ($row) {
           
           
           
           
            $pk = $row->getPk();
           
            if (strpos(request()->url(), '/project/cloneone/')===false){
               
                $weigh = isset($row['weigh']) && $row['weigh']>0?$row['weigh']:$row[$pk];
                $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $weigh,'admin_id'=>\app\admin\library\Auth::instance()->id,'py'=>Pinyin::get($row['title'],true),'pinyin'=>Pinyin::get($row['title'],false)]);
            }
            
            
            
            
            
            
            
            
            $nodes = self::backtrace($row[$pk]);
            $row->getQuery()->where($pk, $row[$pk])->update(['deep' => count($nodes),'nodes'=>implode(",", $nodes)]);
            if (strpos(request()->url(), '/project/cloneone/')===false){
                if (strpos(request()->url(), '/cloneone')!==false){
                    $str = '_'.__('btn_clone');
                    $title = preg_replace("/{$str}/", "", $row['title'],1);
                    Progress::addLog('page_clone',request()->param('ids'),$title);
                } else {
                    Progress::addLog('page_add',$row[$pk],$row['title']);
                }
            } 
        });

        self::afterUpdate(function ($row) {
            self::handleAfterUpdate($row);
        });

        self::afterDelete(function ($row) {
           
           
           
           
           
           
            if($row->deletetime>0 && time() - $row->deletetime<=1) {
               
                Progress::addLog('page_soft_delete',$row['id'],$row['title']);
            } else {
               
                Progress::addLog('page_hard_delete',$row['id'],$row['title']);
            }
            Cache::tag('knowbase')->rm('getHotPages');
        });

        self::beforeWrite(function ($row){
            $content = trim($row->content);
            if (!$content){
                $row->content = '';
            }
        });
        
        self::afterWrite(function ($row){
            Cache::tag('knowbase')->rm('getHotPages');
        });
    }
    
    public static function handleAfterUpdate(&$row){
        if (strpos(request()->url(), '/knowbase/document')!==false){
            return;
        }

       
       
       
       
        
        static $isUpdate = 0;
        if (!$isUpdate){
            $pk = $row->getPk();
            $row->getQuery()->where($pk, $row[$pk])->update(['py'=>Pinyin::get($row['title'],true),'pinyin'=>Pinyin::get($row['title'],false)]);
           
           
           
           
           
           
           
           
            if (!$row['deletetime']) {
                $nodes = self::backtrace($row[$pk]);
                $row->getQuery()->where($pk, $row[$pk])->update(['deep' => count($nodes),'nodes'=>implode(",", $nodes)]);
               
                if ($row['pid']!=$row->origin['pid']) {
                   
                    $nodes = self::getAllNodes($row[$pk]);
                    foreach ($nodes as $id) {
                        $child_nodes = self::backtrace($id);
                        $row->getQuery()->where($pk, $id)->update(['deep' => count($child_nodes),'nodes'=>implode(",", $child_nodes)]);
                    }
                }
            }

            if (request()->post('row.sync_switch',0,'intval')) {
               
                $nodes = self::getAllNodes($row[$pk]);
                if ($nodes) {
                    self::whereIn('id',$nodes)->update(['access_type'=>3]);
                }
            }
           
            if ($row->origin['content'] && $row->origin['content']!=$row->content) {
                ProjectPageHistory::create(
                    [
                        'knowbase_project_id'=>$row['knowbase_project_id'],
                        'knowbase_project_page_id'=>$row[$pk],
                        'admin_id'=>\app\admin\library\Auth::instance()->id,
                        'content'=>$row->origin['content'],
                        'new_content'=>$row->content,
                    ]
                );
            }
            Cache::tag('knowbase')->rm('getNodes_'.$row['id']);
             if (strpos(request()->url(), '/ajax/weigh')!==false) {
                Progress::addLog('page_weight',$row['id'],$row['title'].'，排序值:'.$row['weigh']);
            } else if (strpos(request()->url(), '/restore')!==false){
                Progress::addLog('page_restore',$row['id'],$row['title']);
            } else if (strpos(request()->url(), '/del')===false && strpos(request()->url(), '/add')===false && strpos(request()->url(), '/cloneone')===false){
                Progress::addLog('page_update',$row['id'],$row['title']);
            }
            
            $isUpdate = 1;
        }
    }

    public function getTypeList()
    {
        return ['dir' => __('Type dir'), 'file' => __('Type file'), 'url' => __('Type url')];
    }

    public function getAccessTypeList()
    {
        return ['0' => __('Access_type 0'), '1' => __('Access_type 1'), '2' => __('Access_type 2'), '3' => __('Access_type 3'), '4' => __('Access_type 4')];
    }


    public function getTypeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['type']) ? $data['type'] : '');
        $list = $this->getTypeList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getAccessTypeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['access_type']) ? $data['access_type'] : '');
        $list = $this->getAccessTypeList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public static function getParentPage($pid, $project_id)
    {
       return self::where('id',$pid)->where('knowbase_project_id',$project_id)->find();
    }

    /**
     * 追溯某个节点的父节点个数 包含自身
     * @param $id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function backtrace($id)
    {
        $tasks   = [$id];
        $results = [];

        while (count($tasks)) {
            $cur_id = (int)array_pop($tasks);
            $row    = self::get($cur_id);
            $pid    = $row['pid'];

            $results[] = $cur_id;

            if ($pid > 0) {
                $tasks[] = $pid;
            }
        }

        return array_reverse($results);
    }

    /**
     * 查找某个节点下的所有子节点包含叶子节点 不包含自身
     * @param $pid 父结点ID
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getAllNodes($pid,$onlyId=true)
    {
        $tasks   = [$pid];
        $results = [];

        while (count($tasks)) {
            $cur_id = (int)array_pop($tasks);
            $rows = collection(self::useGlobalScope(false)->where('pid',$cur_id)->select())->toArray();
            foreach ($rows as $row) {
                if ($onlyId) {
                    $results[] = $row['id'];
                } else {
                    $results[] = $row;
                }
                $tasks[] = $row['id'];
            }
        }

        return $results;
    }


    public static function getList($project,$select_id,&$list)
    {
       
        $auth = \app\common\library\Auth::instance();
        if (Cache::tag('knowbase')->has('getList_'.$project['id'])) {
           $pages = Cache::tag('knowbase')->get('getList_'.$project['id']);
        } else {
            $pages = collection(self::where('knowbase_project_id',$project['id'])
                ->field('content,createtime,updatetime,knowbase_project_id,status_switch,deletetime,admin_id',true)
                ->where('status_switch',1)
                ->order('weigh','desc')
                ->select())
                ->toArray();
            Cache::tag('knowbase')->set('getList_'.$project['id'], $pages, 60);
        }

       
        $groupPages = knowbase_groupbyid($pages);
       
        
        if (Cache::tag('knowbase')->has('getEmptyContent_'.$project['id'])) {
           $emptyContentPages = Cache::tag('knowbase')->get('getEmptyContent_'.$project['id']);
        } else {
            $emptyContentPages = knowbase_groupbyid(collection(self::where('knowbase_project_id',$project['id'])
                ->field('id,title')
                ->where('status_switch',1)
                ->where('type','dir')
                ->whereRaw("length(content)=0")
                ->select())->toArray());
            Cache::tag('knowbase')->set('getEmptyContent_'.$project['id'], $emptyContentPages, 60);
        }

       
        $urls = array_filter($pages,function ($v){
            return $v['type']=='url';
        });
        $contents = [];
        if ($urls) {
            $contents = knowbase_groupbyid(collection(self::whereIn('id',array_column($urls,'id'))->field('id,content')->select()));
        }
        
        foreach ($pages as &$v){
           
            if ($v['type']=='url') {
                 $v['url'] = $contents[$v['id']]['content'];
                 $v['menuclass'] = 'menu_url';
            } else {
                $v['url'] = empty($emptyContentPages[$v['id']])?knowbase_page_addon_url($project,$v):"javascript:;";
                $v['menuclass'] = $v['type']=='dir'?'menu_dir':'menu_file';
            }
            
            $v['menutabs'] = 'data-id="'.$v['id'].'"';
            $v['extend'] = '';
            $v['icon'] = '';
            unset($v);
        }
        $showSubmenu = false;
       
        Tree::instance()->init($pages);
        $list = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0),'title');
       
        if ($select_id<=0 && count($list)>0) {
            $select_id = $list[0]['id'];
        }
        $menu = Tree::instance()->getTreeMenu(
            0,
            '<li class="@class"><a @extend href="@url@addtabs" @menutabs class="@menuclass" url="@url" py="@py" pinyin="@pinyin"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret @badge</span></a> @childlist</li>',
            $select_id,
            '',
            'ul',
            'class="treeview-menu' . ($showSubmenu ? ' menu-open' : '') . '"'
        );
        $menu = str_replace("?ref=addtabs", '', $menu);
        $menu = str_replace('url="javascript:;"', '', $menu);
        $menu = str_replace('href="javascript:;"', '', $menu);
        if (preg_match_all("/data-id=\"(\d+?)\"\s+?class=\"menu_dir\"/i", $menu, $matches)){
            foreach ($matches[0] as $k=>$match) {
                $id = $matches[1][$k];
                if (empty($emptyContentPages[$id])) {
                   
                    $url = knowbase_page_addon_url($project,$groupPages[$matches[1][$k]]);
                    $menu = str_replace($match, "{$match} href=\"{$url}\"", $menu);
                }else {
                    $menu = str_replace($match, "{$match} href=\"javascript:;\"", $menu);
                }
            }
        }
       
        if (preg_match("/(data-id=\"{$select_id}\"\sclass=)\"(.+?)\"/i", $menu, $match)){
            $menu = str_replace($match[0], "{$match[1]}\"{$match[2]} active\"", $menu);
        }
       
        if ($project['expand_switch']) {
            $menu = preg_replace("/<li\s+?class=\"\s+?treeview\">/", '<li class="treeview treeview-open">', $menu);
            $menu = preg_replace("/<ul\s+?class=\"\s?treeview-menu\">/", '<ul class="treeview-menu menu-open" style="display:block;">', $menu);
        }
        return $menu;
    }

    public static function getDescription($page){
        $description = $page['content'];
        if (preg_match_all("/(^#.+?)\r?\n/m", $description,$matches)){
            foreach ($matches[0] as $v) {
                $description = str_replace($matches[0], '', $description);
            }
        }
        $description = preg_replace("/```[\w\W]+?```/m", '', $description);
        $description = preg_replace("/\|[\w\W]+?\|/m", '', $description);
        $description = preg_replace("/\[([\w\W]+?)\]/m", '$1', $description);
        $description = preg_replace("/\([\w\W]+?\)/m", '', $description);
        $description = preg_replace("/\([\w\W]?\)/m", '', $description);
        $description = preg_replace("/`[\w\W]+?`/m", '', $description);
        $description = preg_replace("/`[\w\W]?`/m", '', $description);
        $description = preg_replace("/\\$[\w\W]+?\\$/m", '', $description);
        $description = preg_replace("/\\$[\w\W]?\\$/m", '', $description);
        $description = strip_tags( str_replace(["\r","\n",'-'], '', $description));
        return mb_substr($description, 0,100).'...';
    }

    /**
     * 返回标题列表
     * @param $page
     * @return string
     */
    public static function getKeywords($page)
    {
        $keywordws = [];
        $content = $page['content'];
        if (preg_match_all("/(^#.+?)\r?\n/m", $content,$matches)){
           
            $keywordws = array_filter($matches[1],function ($v){
                return substr_count($v, '#')==1;
            });
            if (!$keywordws) {
                $keywordws = array_filter($matches[1],function ($v){
                    return substr_count($v, '#')==2;
                });
            }
            if (!$keywordws) {
                $keywordws = array_filter($matches[1],function ($v){
                    return substr_count($v, '#')==3;
                });
            }
             if (!$keywordws) {
                $keywordws = array_filter($matches[1],function ($v){
                    return substr_count($v, '#')==4;
                });
            }
             if (!$keywordws) {
                $keywordws = array_filter($matches[1],function ($v){
                    return substr_count($v, '#')==5;
                });
            }

             if (!$keywordws) {
                $keywordws = array_filter($matches[1],function ($v){
                    return substr_count($v, '#')==6;
                });
            }
        }
        return trim(str_replace(["#"," "], "",implode(",", $keywordws) ));
    }

    /**
     * 检查密码是否通过
     * @param $project 项目
     * @param $page 文档
     * @param $password 密码
     * @return bool
     */
    public static function checkPassword($project,$page,$password='') {
       
        if ($project['access_type']==1 && $page['access_type']==4
        ) {
           
            if (!$password) {
                if (request()->session('page_password_'.$page['id'])) {
                    $password = request()->session('page_password_'.$page['id']);
                }  else if (request()->session('project_password_'.$project['id'])) {
                    $password = request()->session('project_password_'.$project['id']);
                } 
            }

            if ($password!=$project['password']) {
                return false;
            }

           
            Session::set('project_password_'.$project['id'], $password);
        } else if ($page['access_type']==1){
           
            $password = $password?:request()->session('page_password_'.$page['id']);
            if ($password!=$page['password']) {
                return false;
            }
        }  else if ($page['access_type']==3){
            $result = self::getParentAccessData($project,$page);
           
            if (!$result) {
                return true;
            } else if ($result['access_type']!=1) {
               
                return true;
            }
            

            if (isset($result['image'])) {
               
                $password = $password?:request()->session('project_password_'.$result['id']);
                if ($password!=$result['password']) {
                    return false;
                }
               
                Session::set('project_password_'.$project['id'], $password);
            } else {
                $password = $password?:request()->session('page_password_'.$result['id']);
                if ($password!=$result['password']) {
                    return false;
                }
               
                Session::set('page_password_'.$result['id'], $password);
            }
            
        }
       
        Session::set('page_password_'.$page['id'], $password);
        return true;
    }

    /**
     * 检查用户组是否满足
     * @param $project
     * @param $page
     * @return bool
     */
    public static function checkUserGroup($project,$page,&$allowGrpups) {
        $auth = \app\common\library\Auth::instance();
        $group_id = 0;
        if (!is_null($auth->group_id)) {
            $group_id = $auth->group_id;
        }

        if ($project['access_type']==2 && $page['access_type']==4
        ) {
            $groups = array_filter(explode(",", $project['user_group_ids']));
            if (!in_array($group_id, $groups)) {
                return false;
            }
        } else if ($page['access_type']==2){
            $groups = array_filter(explode(",", $page['user_group_ids']));
            if (!in_array($group_id, $groups)) {
                return false;
            }
        }  else if ($page['access_type']==3){
            $result = self::getParentAccessData($project,$page);
           
            if (!$result) {
                return true;
            } else if ($result['access_type']!=2) {
               
                return true;
            }
            $groups = array_filter(explode(",", $result['user_group_ids']));
            if (!in_array($group_id, $groups)) {
                return false;
            }
        }
        return true;
    }

    /***
     * 获取结点ID列表的数据
     * @param $item
     * @return mixed
     */
    public static function getNodes($item)
    {
        if (!Cache::tag('knowbase')->has('getNodes_'.$item['id'])) {
            $nodesList = array_filter(explode(",",$item['nodes']));
            $result = $nodesList? knowbase_groupbyid(collection( self::whereIn('id', $nodesList)->field('id,pid,title,access_type,password,user_group_ids')->select())->toArray(),'id'):[];
            Cache::tag('knowbase')->set('getNodes_'.$item['id'], $result, 300);
            return $result;
        } else {
            return Cache::tag('knowbase')->get('getNodes_'.$item['id']);
        }

    }

    /**
     * 获取对应文档的同父级权限
     * @param $project
     * @param $item
     * @return void
     */
    public static function getParentAccessData($project,$item)
    {
        if ($item['access_type']!=3) {
            return false;
        }
        $nodes = self::getNodes($item);
        if (!$nodes) {
            return false;
        }
        $parentNodes = array_filter(explode(",", $item['nodes']));
       
        array_pop($parentNodes);

        if (count($parentNodes)==0) {
           
             return $project;
        }

         while($pid = array_pop($parentNodes)) {

            if ($nodes[$pid]['access_type']==4) {
                return $project;
            }

            if ($nodes[$pid]['access_type']!=3) {
                return $nodes[$pid];
            }

             if (count($parentNodes)==0) {
               
                 return $project;
            }

         }
    }

    /**
     * 是否有权进去该项目
     * @param $project
     * @param $page
     * @return bool
     */
    public static function canAccess($project,$page=[])
    {
        return true;
    }

    public function histories()
    {
        return $this->hasMany(ProjectPageHistory::class, 'knowbase_project_page_id', 'id');
    }
    
    public function project()
    {
        return $this->belongsTo(Project::class, 'knowbase_project_id', 'id');
    }
    
}
